
#include <BFolder>
#include <BLabel>
#include <BGridLayout>
#include <BHBoxLayout>
#include <BVBoxLayout>
#include <BGroupBox>
#include <BApplication>
#include <BSystem>
#include <BPainter>
#include <BStyle>

//#include <StringUtils.h>
#include "FontDialog.h"

FontDialog::FontDialog(BWidget* parent) : BDialog(parent)
{
	BGridLayout* gridLayout = new BGridLayout();
	{
		BLabel* familyLabel = new BLabel("Family");
		familyLabel->setName("family");
		_familyEdit = new BLineEdit();
		_familyEdit->setReadOnly(true);
		_familyListWidget = new BListWidget();
		_familyListWidget->setName("family");
		_familyListWidget->setSelectMode(Select_Single);

		_encodingEdit = new BLineEdit();
		_encodingEdit->setReadOnly(true);
		_encodingListWidget = new BListWidget();
		_encodingListWidget->setSelectMode(Select_Single);

		_sizeSpinBox = new BSpinBox(6, 100);
		_sizeListWidget = new BListWidget();

		gridLayout->addWidget(0, 0, familyLabel);
		gridLayout->addWidget(1, 0, _familyEdit);
		gridLayout->addWidget(2, 0, _familyListWidget);

		gridLayout->addWidget(0, 1, new BLabel("Encoding"));
		gridLayout->addWidget(1, 1, _encodingEdit);
		gridLayout->addWidget(2, 1, _encodingListWidget);

		gridLayout->addWidget(0, 2, new BLabel("Size"));
		gridLayout->addWidget(1, 2, _sizeSpinBox);
		gridLayout->addWidget(2, 2, _sizeListWidget);

		gridLayout->setRowStretch(2, 999);
		gridLayout->setColumnStretch(0, 10);

	}

	BGroupBox* effectsGroupBox = new BGroupBox("Options");
	{
		_boldCheckBox = new BCheckBox("Bold");
		_italicCheckBox = new BCheckBox("Italic");
		_monospaceCheckBox = new BCheckBox("monospace");

		_tabSizeSpinBox = new BSpinBox(1, 6);
		_tabSizeSpinBox->setPrefix("Tab-Size:");
		_tabSizeSpinBox->setPrefixAlign(Align_LeftCenter);

		BVBoxLayout* vlayout = new BVBoxLayout(effectsGroupBox);
		vlayout->addWidget(_boldCheckBox);
		vlayout->addWidget(_italicCheckBox);
		vlayout->addWidget(_monospaceCheckBox);
		vlayout->addWidget(_tabSizeSpinBox);
	}

	BGroupBox* sampleGroupBox = new BGroupBox("Sample");
	sampleGroupBox->setSizePolicy(Policy_Fixed | Policy_Expanding);
	sampleGroupBox->setFixedSize(200, 100);
	{
		_sampleLabel = new BLabel("AaBbYyZz");
		_sampleLabel->setName("sample");
		_sampleLabel->setAlign(Align_Center);
		BLayout* layout = new BLayout(sampleGroupBox);
		layout->setWidget(_sampleLabel);
	}

	BHBoxLayout* hlayout = new BHBoxLayout();
	hlayout->addWidget(effectsGroupBox);
	hlayout->addWidget(sampleGroupBox);

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addLayout(gridLayout);
	vlayout->addLayout(hlayout, 0);

	BHBoxLayout* bottomLayout = new BHBoxLayout(this, Part_Bottom);
	{
		_confirmButton = new BButton("Confirm");
		_cancelButton = new BButton("Cancel");
		bottomLayout->addSpring();
		bottomLayout->addWidget(_confirmButton);
		bottomLayout->addWidget(_cancelButton);
	}

	connect(_sizeSpinBox, Signal_EditFinished, &FontDialog::slotSizeEditFinished);
	connect(_familyListWidget, Signal_Framed, &FontDialog::slotFamilyListWidgetFramed);
	connect(_familyListWidget, Signal_SelectionChanged, &FontDialog::slotFamilySelectionChanged);
	connect(_encodingListWidget, Signal_SelectionChanged, &FontDialog::slotEncodingSelectionChanged);
	connect(_sizeListWidget, Signal_SelectionChanged, &FontDialog::slotSizeSelectionChanged);

	connect(_boldCheckBox, Signal_Toggled, &FontDialog::slotBoldCheckBoxToggled);
	connect(_italicCheckBox, Signal_Toggled, &FontDialog::slotItalicCheckBoxToggled);
	connect(_monospaceCheckBox, Signal_Toggled, &FontDialog::slotMonospaceCheckBoxToggled);
	connect(_tabSizeSpinBox, Signal_EditFinished, &FontDialog::slotTabSizeEditFinished);

	connect(_confirmButton, Signal_Clicked, &FontDialog::slotConfirmButtonClicked);
	connect(_cancelButton, Signal_Clicked, &FontDialog::slotCancelButtonClicked);

	BFolder folder0(BApplication::libPath() + "/font");
	if (folder0.open())
	{
		for (int j = 0; j < folder0.entryCount(); j++)
		{
			BEntry* entry = folder0.entry(j);
			BString name = entry->name();
			name -= name.dext();
			_familyListWidget->addItem(name);
		}
	}
	BFolder folder1(BApplication::appPath() + "/font");
	if (folder1.open())
	{
		for (int j = 0; j < folder1.entryCount(); j++)
		{
			BEntry* entry = folder1.entry(j);
			BString name = entry->name();
			name -= name.dext();
			_familyListWidget->addItem(name);
		}
	}
	BFolder folder2(BSystem::FontPath());
	if (folder2.open())
	{
		for (int j = 0; j < folder2.entryCount(); j++)
		{
			BEntry* entry = folder2.entry(j);
			BString name = entry->name();
			if (name.endWith(".ttf") || name.endWith(".ttc") || name.endWith(".otf"))
			{
				name -= name.dext();
				_familyListWidget->addItem(name);
			}
		}
	}

	_sizeListWidget->addItem(6)->setAsset(6);
	_sizeListWidget->addItem(10)->setAsset(10);
	_sizeListWidget->addItem(15)->setAsset(15);
	_sizeListWidget->addItem(20)->setAsset(20);
	_sizeListWidget->addItem(25)->setAsset(25);
	_sizeListWidget->addItem(30)->setAsset(30);
	_sizeListWidget->addItem(35)->setAsset(35);
	_sizeListWidget->addItem(40)->setAsset(40);

}
FontDialog::~FontDialog()
{

}

void FontDialog::freshFont()
{
	if (_font)
	{
		if (BListItem* item = _familyListWidget->item(_font->family()))
		{
			item->setSelected(true);
		}
	}
}

Encoding FontDialog::StringToEncoding(const BString& text)
{
	if (text == "unicode")
		return Encoding_Unicode;
	if (text == "gb2312")
		return Encoding_GB2312;
	if (text == "big5")
		return Encoding_Big5;
	if (text == "apple-roman")
		return Encoding_Apple_Roman;
	if (text == "sjis")
		return Encoding_Sjis;
	if (text == "johab")
		return Encoding_Johab;
	if (text == "wansung")
		return Encoding_Wansung;
	if (text == "ms-symbol")
		return Encoding_MS_Symbol;
	return Encoding_None;
}
BString FontDialog::StringFromEncoding(Encoding encoding)
{
	BString text;
	if (encoding == Encoding_Unicode)
		text = "unicode";
	if (encoding == Encoding_GB2312)
		text = "gb2312";
	if (encoding == Encoding_Big5)
		text = "big5";
	if (encoding == Encoding_Apple_Roman)
		text = "apple-roman";
	if (encoding == Encoding_Sjis)
		text = "sjis";
	if (encoding == Encoding_Johab)
		text = "johab";
	if (encoding == Encoding_Wansung)
		text = "wansung";
	if (encoding == Encoding_MS_Symbol)
		text = "ms-symbol";
	return text;
}

void FontDialog::slotSizeEditFinished(BObject* object, const BValue& value)
{
	int size = value;
	_font->setSize(size);
	_sampleLabel->setFont(_font);
}
void FontDialog::slotFamilyListWidgetFramed(BObject* object, const BValue& value)
{
	const BString& sample = _familyListWidget->realStyle()->value(Value_Text);
	if (sample.size())
	{
		const BRect& area = _familyListWidget->area();
		const BRect& crect = _familyListWidget->centerRect();
		BPainter painter(_familyListWidget);
		BListItemArray& visual_items = _familyListWidget->query("visual-items");
		for (int i = 0; i < visual_items.size(); i++)
		{
			BListItem* item = visual_items[i];
			BFont* font = item->asset();
			if (!font)
			{
				font = new BFont(item->text());
				item->setAsset(font);
			}
			painter.setFont(font);
			BRect rect = item->rect();
			rect.left() = area.right();
			rect.right() = crect.right();
			painter.setColor(Color_Text);
			painter.drawText(rect, sample);
		}
	}
}
void FontDialog::slotFamilySelectionChanged(BObject* object, const BValue& value)
{
	if (BListItem* item = _familyListWidget->selectedItem())
	{
		_familyEdit->setText(item->text());
		_familyEdit->setAsset(item);

		if (_font.empty())
		{
			_font = new BFont(item->text(), _sizeSpinBox->value());
		}
		_font->setFamily(item->text());

		_encodingListWidget->clearItems();
		for (int i = 0; i < _font->encodingCount(); i++)
		{
			Encoding encoding = _font->encoding(i);
			BString text = StringFromEncoding(encoding);
			_encodingListWidget->addItem(text)->setAsset(encoding);
		}
		if (BListItem* encodingItem = _encodingListWidget->itemOfAsset(_font->encoding()))
			encodingItem->setSelected(true);
		else
			_encodingListWidget->clearSelection();
		_encodingEdit->setText(StringFromEncoding(_font->encoding()));

		if (BListItem* sizeItem = _sizeListWidget->itemOfAsset(_font->size()))
			sizeItem->setSelected(true);
		else
			_encodingListWidget->clearSelection();
		_sizeSpinBox->setValue(_font->size());

		_boldCheckBox->setChecked(_font->bold());
		_italicCheckBox->setChecked(_font->italic());
		_monospaceCheckBox->setChecked(_font->monospace());
		_tabSizeSpinBox->setValue(_font->tabSize());
	}
	_sampleLabel->setFont(_font);
}
void FontDialog::slotEncodingSelectionChanged(BObject* object, const BValue& value)
{
	if (BListItem* item = _encodingListWidget->selectedItem())
	{
		Encoding encoding = item->asset();
		_font->setEncoding(encoding);
		_encodingEdit->setText(item->text());
	}
	_sampleLabel->setFont(_font);
}
void FontDialog::slotSizeSelectionChanged(BObject* object, const BValue& value)
{
	if (BListItem* item = _sizeListWidget->selectedItem())
	{
		int size = item->asset();
		_font->setSize(size);
		_sizeSpinBox->setValue(size);
	}
	_sampleLabel->setFont(_font);
}

void FontDialog::slotBoldCheckBoxToggled(BObject* object, const BValue& value)
{
	bool checked = value;
	_font->setBold(checked);
	_sampleLabel->setFont(_font);
}
void FontDialog::slotItalicCheckBoxToggled(BObject* object, const BValue& value)
{
	bool checked = value;
	_font->setItalic(checked);
	_sampleLabel->setFont(_font);
}
void FontDialog::slotMonospaceCheckBoxToggled(BObject* object, const BValue& value)
{
	bool checked = value;
	_font->setMonospace(checked);
	_sampleLabel->setFont(_font);
}
void FontDialog::slotTabSizeEditFinished(BObject* object, const BValue& value)
{
	int tabSize = value;
	_font->setTabSize(tabSize);
	_sampleLabel->setFont(_font);
}

void FontDialog::slotConfirmButtonClicked(BObject* object, const BValue& value)
{
	this->setAsset(_font);
	this->close(true);
}
void FontDialog::slotCancelButtonClicked(BObject* object, const BValue& value)
{
	this->close();
}

void FontDialog::showEvent(const BEvent& event)
{
	_font = (BFont*)this->asset();
	if (_font.empty())
	{
		_font = new BFont();
	}
	freshFont();
	BDialog::showEvent(event);
}
void FontDialog::hideEvent(const BEvent& event)
{
	BDialog::hideEvent(event);
}
